package com.example.scaffold.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.scaffold.common.bean.PageResult;
import com.example.scaffold.common.exception.BusinessException;
import com.example.scaffold.order.bean.OrderDTO;
import com.example.scaffold.order.bean.OrderEditParam;
import com.example.scaffold.order.bean.OrderQueryParam;
import com.example.scaffold.order.bean.OrderVO;
import com.example.scaffold.order.converter.OrderConverter;
import com.example.scaffold.order.entity.Order;
import com.example.scaffold.order.mapper.OrderMapper;
import com.example.scaffold.order.service.OrderService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.example.scaffold.common.constant.RedisKeyConstant.ORDER_INFO_KEY;

/**
 * 订单服务实现类
 * 遵循阿里手册：服务实现类命名规范，缓存处理规范，事务管理规范
 *
 * @author example
 */
@Service
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    private static final Logger log = LoggerFactory.getLogger(OrderServiceImpl.class);
    
    private final RedisTemplate<String, Object> redisTemplate;
    private final OrderMapper orderMapper;
    private final OrderConverter orderConverter;

    /**
     * 根据ID查询订单，使用缓存
     * 遵循阿里手册：缓存更新策略，缓存穿透防护
     */
    @Override
    public OrderDTO getOrderById(Long id) {
        if (id == null || id <= 0) {
            log.warn("查询订单ID不合法:{}", id);
            throw new BusinessException("订单ID不合法");
        }
        
        // 先查询缓存
        String cacheKey = String.format(ORDER_INFO_KEY, id);
        OrderDTO orderDTO = (OrderDTO) redisTemplate.opsForValue().get(cacheKey);
        if (orderDTO != null) {
            log.info("从缓存获取订单信息，订单ID:{}", id);
            return orderDTO;
        }
        
        // 缓存未命中，查询数据库
        Order order = getById(id);
        if (order == null) {
            log.warn("订单不存在，订单ID:{}", id);
            throw new BusinessException("订单不存在");
        }
        
        // 转换为DTO并缓存
        orderDTO = BeanUtil.copyProperties(order, OrderDTO.class);
        redisTemplate.opsForValue().set(cacheKey, orderDTO, 30, TimeUnit.MINUTES);
        log.info("查询数据库并缓存订单信息，订单ID:{}", id);
        
        return orderDTO;
    }

    /**
     * 创建订单，事务管理
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOrder(OrderEditParam param) {
        // 检查用户名是否已存在
        Order existingOrder = orderMapper.selectByUsername(param.getUsername());
        if (existingOrder != null) {
            log.warn("用户名已存在:{}", param.getUsername());
            throw new BusinessException("用户名已存在");
        }
        
        // 转换为实体
        Order order = BeanUtil.copyProperties(param, Order.class);
        order.setStatus(1); // 默认正常状态
        order.setFlag(true); // 默认标志为true
        order.setDeleted(0); // 未删除
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        
        // 保存订单
        save(order);
        log.info("创建订单成功，订单ID:{}", order.getId());
        
        return order.getId();
    }

    /**
     * 更新订单，更新缓存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrder(Long id, OrderEditParam param) {
        Order order = getById(id);
        if (order == null) {
            log.warn("更新订单不存在，订单ID:{}", id);
            throw new BusinessException("订单不存在");
        }
        
        // 复制属性，忽略null值
        BeanUtil.copyProperties(param, order, "id", "createTime");
        order.setUpdateTime(LocalDateTime.now());
        
        // 更新数据库
        boolean result = updateById(order);
        
        // 更新缓存
        if (result) {
            String cacheKey = String.format(ORDER_INFO_KEY, id);
            OrderDTO updatedDTO = BeanUtil.copyProperties(order, OrderDTO.class);
            redisTemplate.opsForValue().set(cacheKey, updatedDTO, 30, TimeUnit.MINUTES);
            log.info("更新订单及缓存成功，订单ID:{}", id);
        }
        
        return result;
    }

    /**
     * 删除订单，删除缓存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteOrder(Long id) {
        // 逻辑删除
        // Order order = new Order();
        // order.setId(id);
        // order.setDeleted(1);
        // order.setUpdateTime(LocalDateTime.now());
        // boolean result = updateById(order);
        boolean result = removeById(id);
        
        // 删除缓存
        if (result) {
            String cacheKey = String.format(ORDER_INFO_KEY, id);
            redisTemplate.delete(cacheKey);
            log.info("删除订单及缓存成功，订单ID:{}", id);
        }
        
        return result;
    }

    @Override
    public PageResult<OrderVO> listOrder(OrderQueryParam param) {
        IPage<Order> page = new Page<>(param.getPageNum(), param.getPageSize());
        IPage<Order> resultPage = orderMapper.selectPage(page, null);
        List<OrderVO> orderVOs = resultPage.getRecords().stream()
                .map(orderConverter::toVO)
                .collect(Collectors.toList());

        PageResult<OrderVO> pageResult = new PageResult<>();
        pageResult.setTotal(resultPage.getTotal());
        pageResult.setPages(resultPage.getPages());
        pageResult.setPageNum(param.getPageNum());
        pageResult.setPageSize(param.getPageSize());
        pageResult.setList(orderVOs);
        return pageResult;

    }
}